package yu.code.yurpc.server;

import io.vertx.core.Handler;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.core.http.HttpServerResponse;
import yu.code.yurpc.RpcApplication;
import yu.code.yurpc.model.RpcRequest;
import yu.code.yurpc.model.RpcResponse;
import yu.code.yurpc.registry.LocalRegistry;
import yu.code.yurpc.serializer.JdkSerializer;
import yu.code.yurpc.serializer.Serializer;
import yu.code.yurpc.serializer.SerializerFactory;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.ServiceLoader;

//HTTP 请求处理器
public class HttpServerHandler implements Handler<HttpServerRequest> {
    /**
     * 处理请求
     * @param httpServerRequest
     */
    @Override
    public void handle(HttpServerRequest httpServerRequest) {
        //指定序列化器
        final Serializer serializer = SerializerFactory.getInstance(RpcApplication.getRpcConfig().getSerializer());
        //记录日志
        System.out.println("Received request:"+httpServerRequest.method()+" "+httpServerRequest.uri());
        //异步处理Http请求逻辑
        httpServerRequest.bodyHandler(body -> {
            byte[] bytes = body.getBytes();
            RpcRequest rpcRequest = null;
            try {
                //反序列化请求对象
                rpcRequest = serializer.deserialize(bytes,RpcRequest.class);
            } catch (IOException e) {
                e.printStackTrace();
            }
            //构造响应对象对象
            RpcResponse rpcResponse = new RpcResponse();
            //如果请求为null，直接返回
            if(rpcRequest==null){
                rpcResponse.setMessage("request is null");
                doResponse(httpServerRequest,rpcResponse, serializer);
                return;
            }
            try {
                //获取需要调用的服务实现类，通过反射调用方法
                String serviceName = rpcRequest.getServiceName();
                Class<?> aClass = LocalRegistry.get(serviceName);
                Method method = aClass.getMethod(rpcRequest.getMethodName(), rpcRequest.getParameterTypes());
                Object result = method.invoke(aClass.newInstance(), rpcRequest.getParameters());
                //封装成功响应对象
                rpcResponse.setData(result);
                rpcResponse.setDataType(result.getClass());
                rpcResponse.setMessage("success");
            } catch (Exception e) {
                //封装失败响应对象
                e.printStackTrace();
                rpcResponse.setException(e);
                rpcResponse.setMessage("fail");
            }
            //响应
            doResponse(httpServerRequest,rpcResponse, serializer);
        });
    }

    /**
     * 响应
     * @param request
     * @param rpcResponse
     * @param serializer
     */
    void doResponse(HttpServerRequest request, RpcResponse rpcResponse,Serializer serializer){
        HttpServerResponse response = request
                .response()
                .putHeader("content-type", "application/json");
        try {
            //序列化响应对象
            byte[] bytes = serializer.serialize(rpcResponse);
            //写入响应
            response.end(Buffer.buffer(bytes));
        } catch (IOException e) {
            e.printStackTrace();
            response.end(Buffer.buffer());
        }
    }
}
